/*******************************************************************************
 * Copyright (c) 2014 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Ian Craggs - initial API and implementation and/or initial documentation
 *    Sergio R. Caprile - clarifications and/or documentation extension
 *******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "MQTTClient.h"
#include "wifi_sta_connect.h"

#include "cJSON.h"


#include "iot_gpio.h"
#include "iot_gpio_ex.h"
#include "iot_pwm.h"

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

#define WIFI_SSID "MY_WiFi"
#define WIFI_PWD "12345678"

#define HOST_ADDR " "    //华为云mqtt接入地址

#define CLIENT_ID   " "          //华为云mqtt接入ID
#define DEVICE_ID   " "                         //华为云mqtt的接入用户名
#define PASS_WORD   " "              //华为云mqtt的接入用户密码

#define PUBLISH_TOPIC "$oc/devices/"DEVICE_ID"/sys/properties/report"
#define SUBCRIB_TOPIC "$oc/devices/"DEVICE_ID"/sys/commands/#" ///request_id={request_id}"
#define RESPONSE_TOPIC "$oc/devices/"DEVICE_ID"/sys/commands/response" ///request_id={request_id}"


#define LED_GPIO_IDX 5
#define MOTOR_GPIO_IDX 2
#define MOTOR_PWM_CHN 2
int g_motor_level;

int motor_speed(int speed){

    if(speed <0){
        speed = 0;
    }
    int level = (speed > 5) ? 5 : speed ;
    

    if(speed == 0){
        //close motor
        IoTPwmStop(MOTOR_PWM_CHN);
    }else{
        IoTPwmStart(MOTOR_PWM_CHN, level, 40000);
    }

    g_motor_level = level;

}


int motor_init()
{
    IoTGpioInit(MOTOR_GPIO_IDX);
    IoTGpioSetFunc(MOTOR_GPIO_IDX, IOT_GPIO_FUNC_GPIO_2_PWM2_OUT);
    IoTGpioSetDir(MOTOR_GPIO_IDX,IOT_GPIO_DIR_OUT);
    IoTPwmInit(MOTOR_PWM_CHN);

}


Network network;
MQTTClient client;

void messageCmdback(char *request_id)
{
    int rc;
    char rsptopic[128]={0};
    sprintf(rsptopic,"%s/request_id=%s",RESPONSE_TOPIC,request_id);
    printf("rsptopic = %s\n",rsptopic);
    //printf("msg=%s\n",data->message->payload);
    MQTTMessage message;
    char payload[300];
    message.qos = 0;
    message.retained = 0;
    message.payload = payload;
    sprintf(payload, "{ \
    \"result_code\": 0, \
    \"response_name\": \"COMMAND_RESPONSE\", \
    \"paras\": { \
        \"result\": \"success\" \
    } \
    }" );
    message.payloadlen = strlen(payload);

    //publish the msg to responese topic
    if ((rc = MQTTPublish(&client, rsptopic, &message)) != 0) {
        printf("Return code from MQTT publish is %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        
    }
}

void messageArrived(MessageData* data)
{
    int rc;
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
           data->message->payloadlen, data->message->payload);

    /*
        /xx//x/x//x/requets_id=123456
    */

   //get request id
    char *request_id_idx=NULL;
    char request_id[20]={0};
    request_id_idx = strstr(data->topicName->lenstring.data,"request_id=");
    strncpy(request_id,request_id_idx+11,19);
    printf("request_id = %s\n",request_id);

    //create response topic
    char rsptopic[128]={0};
    sprintf(rsptopic,"%s/request_id=%s",RESPONSE_TOPIC,request_id);
    printf("rsptopic = %s\n",rsptopic);
    printf("msg=%s\n",data->message->payload);
#if 1
    //response message
    MQTTMessage message;
    char payload[300];
    message.qos = 0;
    message.retained = 0;
    message.payload = payload;
    sprintf(payload, "{ \
    \"result_code\": 0, \
    \"response_name\": \"COMMAND_RESPONSE\", \
    \"paras\": { \
        \"result\": \"success\" \
    } \
    }" );
    message.payloadlen = strlen(payload);

    //publish the msg to responese topic
    if ((rc = MQTTPublish(&client, rsptopic, &message)) != 0) {
        printf("Return code from MQTT publish is %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        
    }
    #endif
    cJSON *root = cJSON_ParseWithLength( data->message->payload, data->message->payloadlen);
    if(root != NULL){
        cJSON *cmd_name = cJSON_GetObjectItem(root,"command_name");
        if(cmd_name != NULL){
            char *cmd_name_str = cJSON_GetStringValue(cmd_name);

            if(strcmp(cmd_name_str,"Led") == 0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *status_obj = cJSON_GetObjectItem(para_obj,"led_control");
                if(status_obj != NULL){
                 char *data = NULL;
                 data = cJSON_GetStringValue(status_obj);
                 if(data != NULL){
                    if(strcmp(data,"OFF") == 0)
                    {
                        IoTGpioSetOutputVal(8,0);
                        printf("led_sta = %d\n",0);
                    }
                    else
                    {
                        IoTGpioSetOutputVal(8,1);
                        printf("led_sta = %d\n",1);
                    }
                    
                 }
                }
                messageCmdback(request_id);
            }
            

        }

        cJSON_Delete(root);

    }

}

static void MQTTDemoTask(void)
{

    printf(">> MQTTDemoTask ...\n");
    WifiConnect(WIFI_SSID, WIFI_PWD);
    printf("Starting ...\n");
    int rc, count = 0;
    // MQTTClient client;


    NetworkInit(&network);
    printf("NetworkConnect  ...\n");


begin:
    NetworkConnect(&network, HOST_ADDR, 1883);
    printf("MQTTClientInit  ...\n");
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = CLIENT_ID;//DEVICE_ID; //"1234abcdef_0_0_2022101103";

    MQTTString userName = MQTTString_initializer;
    userName.cstring = DEVICE_ID; //"1234abcdef"; //deviceID

    MQTTString password = MQTTString_initializer;
    password.cstring = PASS_WORD;//"24ff6d0e45ed197f978be2a1c21bc18467d6ce75d07ac77b62ca827dc0ccf82d";//"12345678"; //"be64416f73bad92de15bd2d266c71dbce661fb985adfa5feb7e7f68e51bda8bf";

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;

    data.username = userName;
	data.password = password;

    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 60;
    data.cleansession = 1;

    printf("MQTTConnect  ...\n");
    rc = MQTTConnect(&client, &data);
    if (rc != 0) {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(200);
        goto begin;
    }

    printf("MQTTSubscribe  ...\n");
    rc = MQTTSubscribe(&client, SUBCRIB_TOPIC, 0, messageArrived);

    if (rc != 0) {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(200);
        goto begin;
    }

    while (1) {
        

        MQTTMessage message;
        // char *publishtopic="$oc/devices/test_fan_1/sys/properties/report";

        char payload[500]={0};

         cJSON *root = cJSON_CreateObject();

        if(root != NULL){

            cJSON *serv_arr = cJSON_AddArrayToObject(root, "services");

            cJSON *arr_item =  cJSON_CreateObject();

            cJSON_AddStringToObject(arr_item,"service_id","smart_fan");

            cJSON *pro_obj = cJSON_CreateObject();
            cJSON_AddItemToObject(arr_item,"properties",pro_obj);
            cJSON_SetIntValue(pro_obj, 2);
            
            cJSON_AddNumberToObject(pro_obj,"Temperature",19);
            cJSON_AddNumberToObject(pro_obj,"Humidity",70);
               
           

            cJSON_AddItemToArray(serv_arr,arr_item);

            char *palyload_str = cJSON_PrintUnformatted(root);

            strcpy(payload,palyload_str);

            cJSON_free(palyload_str);
            cJSON_Delete(root);

        }
     
        message.qos = 0;
        message.retained = 0;
        message.payload = payload;
     
        message.payloadlen = strlen(payload);

        if ((rc = MQTTPublish(&client, PUBLISH_TOPIC, &message)) != 0) {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            goto begin;
        }else{
            printf("mqtt publish success:%s\n",payload);
        }
        MQTTYield(&client, 5000);
        sleep(3);
        // osDelay(500);
    }
}    

static void MQTTDemo(void)
{
    osThreadAttr_t attr;

    IoTGpioInit(8);
    IoTGpioSetFunc(8, 0);
    IoTGpioSetDir(8,IOT_GPIO_DIR_OUT);

    attr.name = "MQTTDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)MQTTDemoTask, NULL, &attr) == NULL) {
        printf("[MQTT_Demo] Failed to create MQTTDemoTask!\n");
    }
}

APP_FEATURE_INIT(MQTTDemo);